package com.eis.admin.mvc.controller;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.eis.admin.mvc.bean.FunctionBean;
import com.eis.admin.mvc.bean.StatusRuleDetailBean;
import com.eis.admin.mvc.bean.StatusRuleEditBean;
import com.eis.admin.mvc.controller.base.MVCBaseController;
import com.eis.function.out.rule.comparator.common.RuleComparator;
import com.eis.function.out.rule.model.StatusCondition;
import com.eis.function.out.rule.model.StatusRule;
import com.eis.function.out.rule.model.StatusRules;
import com.eis.persist.dao.FunctionDAO;
import com.eis.persist.dao.UserFunctionDAO;
import com.eis.persist.dao.impl.FunctionDAOImpl;
import com.eis.persist.dao.impl.UserFunctionDAOImpl;
import com.eis.persist.model.function.PersistFunctionSchema;
import com.eis.persist.model.function.PersistFunctionStatus;
import com.eis.persist.model.function.PersistFunctionStatusRule;
import com.eis.persist.model.user.PersistUser;
import com.eis.util.XmlUtil;

@Controller
public class StatusEngineAdminController extends MVCBaseController {
	private static final Logger logger = LoggerFactory
			.getLogger(StatusEngineAdminController.class);
	private UserFunctionDAO userFunctionDAO;
	private XmlUtil xmlUtil;
	public void setXmlUtil(XmlUtil xmlUtil) {
		this.xmlUtil = xmlUtil;
	}

	@Override
	public void setFunctionDataSource(JdbcTemplate functionDataSource) {
		this.functionDataSource = functionDataSource;
		userFunctionDAO = new UserFunctionDAOImpl(this.functionDataSource);
	}

	@RequestMapping(value = "/editStatusRuleDetail")
	public ModelAndView editStatusRule(@ModelAttribute("statusRuleDetailBean") StatusRuleDetailBean statusRuleDetailBean, Model model, HttpServletRequest request) {
		String functionId = "";
		if (request.getParameter("functionId") != null 
				&& request.getParameter("functionId").trim().length() > 0) {
			functionId = request.getParameter("functionId");
			statusRuleDetailBean.setFunctionId(functionId);
			if (request.getParameter("ruleId") != null 
					&& request.getParameter("ruleId").trim().length() > 0) {
				try {
					statusRuleDetailBean.setRuleId(request.getParameter("ruleId"));
					int ruleId = Integer.parseInt(statusRuleDetailBean.getRuleId());
					
					// load function schema
					FunctionDAO functionDAO = new FunctionDAOImpl(functionDataSource);
					List<PersistFunctionSchema> persistFunctionSchemas = functionDAO.getFunctionSchemaByFunctionId(functionId);
					
					model.addAttribute("functionSchemaList", persistFunctionSchemas);
					
					// Comparator List
					List<String> comparatorList = new ArrayList<String>();
					for (RuleComparator comparator : RuleComparator.values()) {
						comparatorList.add(comparator.name());
					}
					model.addAttribute("comparatorList", comparatorList);
					
					// status list
					List<PersistFunctionStatus> statusList = functionDAO.loadFunctionStatuses();
					model.addAttribute("functionStatusList", statusList);
					
					// load status rule
					PersistFunctionStatusRule persistFunctionStatusRule = functionDAO.loadFunctionStatusRule(functionId);
					StatusRules statusRules = null;
					if (persistFunctionStatusRule != null) {
						statusRules = (StatusRules) xmlUtil.parseXml(persistFunctionStatusRule.getRulexml());
						for (StatusRule oneRule : statusRules.getStatusRules()) {
							if (oneRule.getRuleId() == ruleId) {
								statusRuleDetailBean.setEditRuleStatus(Integer.parseInt(oneRule.getStatus()));
								
								statusRuleDetailBean.setStatusConditionList(oneRule.getStatusConditions());
								statusRuleDetailBean.setConditionEditIndex(oneRule.getStatusConditions().size());
								break;
							}
						}
					}
					return new ModelAndView("/function/editStatusRuleDetail", "command", statusRuleDetailBean);
				} catch (Throwable e) {
					logger.error("Exception in action editStatusRuleDetail: ", e);
					return new ModelAndView("commonError");
				}
				
			} else {
				return new ModelAndView("commonError");
			}
			
		} else {
			return new ModelAndView("commonError");
		}
	}
	
	@RequestMapping(value = "/editStatusRule")
	public ModelAndView editStatusRule(@ModelAttribute("editStatusRuleBean") StatusRuleEditBean statusRuleEditBean, Model model, HttpServletRequest request) {
		// load function list
		PersistUser currentUser = super.getCurrentUser(request);
		List<FunctionBean> functions = userFunctionDAO.getFunctionsForList(currentUser.getBizGroup().getId(), 1, 100, null);
		model.addAttribute("functionList", functions);
		
		if (statusRuleEditBean == null) {
			statusRuleEditBean = new StatusRuleEditBean();
		}
		
		if (statusRuleEditBean.getFunctionId() == null || statusRuleEditBean.getFunctionId().trim().length() == 0) {
			String functionId = "";
			if (request.getAttribute("functionId") != null && ((String)request.getAttribute("functionId")).trim().length() > 0) {
				functionId = (String)request.getAttribute("functionId");
			} else if (request.getParameter("functionId") != null 
					&& request.getParameter("functionId").trim().length() > 0) {
				functionId = request.getParameter("functionId");
			}
			statusRuleEditBean.setFunctionId(functionId);
		}
		
		if (statusRuleEditBean.getFunctionId() != null && statusRuleEditBean.getFunctionId().trim().length() > 0) {
			boolean idAvaliable = false;
			for (FunctionBean oneBean : functions) {
				if (oneBean.getFunctionID().equals(statusRuleEditBean.getFunctionId())) {
					statusRuleEditBean.setFunctionName(oneBean.getLabel());
					idAvaliable = true;
				}
			}
			
			if (!idAvaliable) {
				statusRuleEditBean.setFunctionId("");
			} else {
				// load function schema
				FunctionDAO functionDAO = new FunctionDAOImpl(functionDataSource, currentUser.getName());
				List<PersistFunctionSchema> persistFunctionSchemas = functionDAO.getFunctionSchemaByFunctionId(statusRuleEditBean.getFunctionId());
				
				model.addAttribute("functionSchemaList", persistFunctionSchemas);
				
				// Comparator List
				List<String> comparatorList = new ArrayList<String>();
				for (RuleComparator comparator : RuleComparator.values()) {
					comparatorList.add(comparator.name());
				}
				model.addAttribute("comparatorList", comparatorList);
				
				// status list
				List<PersistFunctionStatus> statusList = functionDAO.loadFunctionStatuses();
				model.addAttribute("functionStatusList", statusList);
				Map<String, PersistFunctionStatus> statusMap = new HashMap<String, PersistFunctionStatus>();
				for (PersistFunctionStatus status : statusList) {
					statusMap.put(String.valueOf(status.getId()), status);
				}
				
				// load status rule
				PersistFunctionStatusRule persistFunctionStatusRule = functionDAO.loadFunctionStatusRule(statusRuleEditBean.getFunctionId());
				StatusRules statusRules = null;
				if (persistFunctionStatusRule != null) {
					statusRules = (StatusRules) xmlUtil.parseXml(persistFunctionStatusRule.getRulexml());
					for (StatusRule rule : statusRules.getStatusRules()) {
						// set name
						PersistFunctionStatus status = statusMap.get(rule.getStatus());
						rule.setStatusName(status.getName());
					}
					statusRuleEditBean.setStatusRules(statusRules.getStatusRules());
					if (!"saveEffectDays".equals(statusRuleEditBean.getOperation1())) {
						statusRuleEditBean.setNewRuleEffectDays((int)(statusRules.getEffectTime()/(24 * 60 * 60 * 1000L)));
					}
				} else {
					statusRuleEditBean.setStatusRules(new ArrayList<StatusRule>());
				}
				// complete the customization
				if ("addARule".equals(statusRuleEditBean.getOperation())) {
					// save new rule
					int ruleId = 1; 
					if (persistFunctionStatusRule != null) {
						ruleId = persistFunctionStatusRule.getMaxRuleId() + 1;
					} else {
						statusRules = new StatusRules();
						statusRules.setStatusRules(new ArrayList<StatusRule>());
					}
					StatusRule newRule= new StatusRule();
					statusRules.getStatusRules().add(newRule);
					newRule.setRuleId(ruleId);
					newRule.setStatus(String.valueOf(statusRuleEditBean.getNewRuleStatus()));
					
					List<StatusCondition> realList = new ArrayList<StatusCondition>();
					// remove disabled things
					for (StatusCondition condidtion : statusRuleEditBean.getStatusConditionList()) {
						if (condidtion.isEnabled()) {
							realList.add(condidtion);
						}
					}
					newRule.setStatusConditions(realList);
					
					functionDAO.updateStatusRule(statusRuleEditBean.getFunctionId(), xmlUtil.toXml(statusRules), ruleId);
					statusRuleEditBean.setStatusRules(statusRules.getStatusRules());
				} else if ("saveEffectDays".equals(statusRuleEditBean.getOperation1())) {
					// save new rule
					int ruleId = 0; 
					if (persistFunctionStatusRule == null) {
						statusRules = new StatusRules();
						statusRules.setStatusRules(new ArrayList<StatusRule>());
					} else {
						ruleId = persistFunctionStatusRule.getMaxRuleId();
					}
					statusRules.setEffectTime(statusRuleEditBean.getNewRuleEffectDays() * 24 * 60 * 60 * 1000L);
					functionDAO.updateStatusRule(statusRuleEditBean.getFunctionId(), xmlUtil.toXml(statusRules), ruleId);
				} else if ("deleteRule".equals(statusRuleEditBean.getOperation1())) {
					// delete the rule
					
					if (statusRules != null && statusRules.getStatusRules() != null && statusRules.getStatusRules().size() > 0) {
						int deleteRuleId = Integer.parseInt(statusRuleEditBean.getOperationRuleId());
						List<StatusRule> operatedList = new ArrayList<StatusRule>();
						for (StatusRule oneRule : statusRules.getStatusRules()) {
							if (oneRule.getRuleId() != deleteRuleId) {
								operatedList.add(oneRule);
							}
						}
						statusRules.setStatusRules(operatedList);
						
						functionDAO.updateStatusRule(statusRuleEditBean.getFunctionId(), xmlUtil.toXml(statusRules), persistFunctionStatusRule.getMaxRuleId());
						
						statusRuleEditBean.setStatusRules(statusRules.getStatusRules());
					}
				} else if ("editARule".equals(statusRuleEditBean.getOperation2())) {
					// edit rule
					int editruleId = statusRuleEditBean.getRuleId(); 
					if (statusRules != null && statusRules.getStatusRules() != null && statusRules.getStatusRules().size() > 0) {
						for (StatusRule editRule : statusRules.getStatusRules()) {
							if (editRule.getRuleId() == editruleId) {
								editRule.setStatus(String.valueOf(statusRuleEditBean.getEditRuleStatus()));
								
								List<StatusCondition> realList = new ArrayList<StatusCondition>();
								// remove disabled things
								for (StatusCondition condidtion : statusRuleEditBean.getStatusConditionList()) {
									if (condidtion.isEnabled()) {
										realList.add(condidtion);
									}
								}
								editRule.setStatusConditions(realList);
								
								functionDAO.updateStatusRule(statusRuleEditBean.getFunctionId(), xmlUtil.toXml(statusRules), persistFunctionStatusRule.getMaxRuleId());
								statusRuleEditBean.setStatusRules(statusRules.getStatusRules());

								break;
							}
						}
					}
				}
			}
		}

		return new ModelAndView("/function/editStatusRule", "command", statusRuleEditBean);
	}
	
}
